// Debug functions
//

#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include "Debug.h"
#include "Utili.h"

#ifdef WIN_PC
#include <windows.h>
#endif

#ifdef WIN_CE
#include <windows.h>
#ifdef __HOLUX__
extern int DbgPrintfW(LPWSTR lpszFmt, ...);
static WCHAR * ConvertStr(char * szIn);
#endif
extern HWND Frame_hwnd;
#endif

#define MAX_STR_LEN  512     // maximum string length for printing

static void (*_report_callback)(char *str) = NULL;

/* Terminate the process */
void d_exit(void)
{
    d_trace("*** abnormal program termination");   
    
    exit(EXIT_FAILURE);
}

#ifdef _DEBUG
#include "../Common/FileSys.h"
FILE* _fpDbg = NULL;

int d_OpenDbgLog(void)
{
	if( _fpDbg == NULL )
	{
		char szFileName[60];

		sprintf( szFileName, "%s/dbg.log", fs_GetRoot() );
		if( ( _fpDbg = fopen( szFileName, "wb" ) ) == NULL )
			return 0;
	}
	return 1;
}

void d_CloseDbgLog(void)
{
	if( _fpDbg )
		fclose( _fpDbg );
}
#endif

/* Send a formatted string to a output location */
void d_trace(char *format,...)
{
    static char str[MAX_STR_LEN];
    va_list arg;

    va_start(arg, format);
    vsprintf(str, format, arg);
    va_end(arg);

    // TODO: output to a file
    // ...
#ifdef _DEBUG
	if( _fpDbg )
	{
		fprintf( _fpDbg, "%s", str );
		fflush( _fpDbg );
	}
#endif

#if defined WIN_PC 
    // Output to the debugger
    OutputDebugString(str);
#elif defined WIN_CE
	#ifdef __HOLUX__
		OutputDebugString(ConvertStr(str));
	#else
		printf( "%s\n", str );
	#endif
	if( strstr( str, "@@@" ) != NULL )
	{
		TCHAR Tstr[256];
		strcat( str, "\n" );

		mbstowcs( Tstr, str, 256 );
		MessageBox( Frame_hwnd,Tstr, _T("LOG"), 0 );
	}
#else
	// Output to stdout (maybe inappropriate?)
    printf(str);
#endif
}

/* Display a diagnostic message */
int d_report(const char *file, int line, const char *literal)
{
    char str[MAX_STR_LEN];
	char unknow[] = "Unknown";

	if (literal == NULL)
		literal = unknow;

	// Prepare the log string
    sprintf(str, "Assertion failed: %s, file %s, line %d\n", literal, file, line);

    // Log this string
    d_trace(str);

    // give a prompt?
    if (_report_callback)
		_report_callback(str);
#ifdef WIN_PC
	else
	{	
		// Prepare the dialog string
		sprintf(str, "Assertion failed: %s\n\n"
					 "File %s, Line %d\n\n"
					 "Continue?", literal, file, line);

		// Display in a message box    
		if (MessageBox(NULL, str, "Oops!", MB_YESNO | MB_ICONSTOP) == IDNO)
			return 1;	// user want to abort
		else
			return 0;	// user want to continue
	}
#elif defined WIN_CE
	{
		TCHAR Tstr[256];
		 sprintf(str, "Assertion failed: %s\n\n"
				 "File %s, Line %d\n\n"
				 "Continue?", literal, file, line);

		mbstowcs( Tstr, str, 256 );
		MessageBox( Frame_hwnd,Tstr, _T("Oops!"), 0 );
		return 0;
	}
#endif   

    return 1;
}

void d_set_report_callback(void (*cb)(char *))
{
	_report_callback = cb;
}


#ifdef TEST_DEBUG
void test_debug(void)
{
	int a = 0, b = 1;

    d_trace("Plz see your debugger if it print: string 10 -10\n"); 
	
    LOG("%s %d %d\n", "string", 10, -10);
    
    TRACE("You should not see this in release build.");

                            // Debug   Release
                            // -----   -------
    ASSERT_ALWAYS(a == 0);  //  p(ass)  p
       
    ASSERT_ALWAYS(a != 0);  //  f(ail)  f

    ASSERT_DEBUG(b != 1);   //  f       p   

    ASSERT(a == b);         //  f       p

    ASSERT(a != b);         //  p       p

    VERIFY(a++);            //  f       p

    ASSERT_ALWAYS(a);       //  p       p
}
#endif	// TEST_DEBUG

// --- Code
#if defined WIN_CE && defined __HOLUX__
WCHAR * ConvertStr(char * szIn)
{
	static WCHAR szOut[MAX_STR_LEN];
	DWORD dwSize = strlen(szIn);
	DWORD count = mbstowcs(NULL, szIn, dwSize);
	memset( szOut, 0, sizeof(WCHAR)*MAX_STR_LEN ); 
	if( count < MAX_STR_LEN ) 
		mbstowcs(szOut, szIn, dwSize);
	return szOut;
}
#endif